package com.chinaedu.oc.util.excel;

import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFFont;
import org.apache.poi.hssf.usermodel.HSSFPatriarch;
import org.apache.poi.hssf.usermodel.HSSFRichTextString;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.ss.util.CellRangeAddress;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PropertiesLoaderUtils;

import com.chinaedu.oc.util.common.StringUtil;
import com.chinaedu.oc.util.csv.ExportUtil;

/**
 * 生成excel
 * @Description: TODO
 * @author A18ccms a18ccms_gmail_com
 * @date 2017年5月26日 下午12:05:40
 *
 * @param <T>
 */
public class ExcelCreater <T>{

	private static int pageSize = 60000;
	/**
	 * 读取配置文件，获取每页条数
	 */
	static {
		Resource resource = new ClassPathResource("/config.properties");
		try {
			Properties props = PropertiesLoaderUtils.loadProperties(resource);
			String num = props.getProperty("excel_page_size");
			try {
				pageSize = Integer.parseInt(num);
			} catch (NumberFormatException e) {
				pageSize = 60000;
			}
		} catch (IOException e) {
			e.printStackTrace();
		}

	}

	//每页多少条数据
	//private int pageSize = 10;
	private int styleNum = 2;

	/**
	 * 生成excel方法
	 * @Description: TODO
	 * @param @param listData 数据
	 * @param @param fields 字段列表
	 * @param @param head 表头列表
	 * @param @param fileName 文件名称
	 * @param @param response response
	 * @param @throws Exception
	 * @return void    返回类型
	 * @throws
	 */
	public void createExcel(List<T> listData,String[] fields, String[] head, String fileName,  HttpServletResponse response,HttpServletRequest request) throws Exception {
		if(head==null || fields == null || head.length != fields.length) {
			throw new RuntimeException("表头信息错误");
		}

		boolean hasData = true;

		ExportUtil et = new ExportUtil();

		//获取父类和自身的属性
		List<String> selfFields = new ArrayList<>();
		List<String> parentFields = new ArrayList<>();
		if(listData!= null && listData.size()>=1) {
			Field[] ffff = listData.get(0).getClass().getDeclaredFields();
			for(Field f : ffff) {
				selfFields.add(f.getName());
			}
			ffff = listData.get(0).getClass().getSuperclass().getDeclaredFields();
			for(Field f : ffff) {
				parentFields.add(f.getName());
			}
		}else {
			hasData = false;
		}

		int rowIndex = 0;
		String titleBase = "页签";
		//获取总页数
		int pages = this.getPages(listData);
		//计算宽度
		int defaultCellWidth = head.length;
		// 声明一个工作薄
		HSSFWorkbook workbook = new HSSFWorkbook();
		//获取样式
		HSSFCellStyle style = CellStyle.getStyle(styleNum,workbook);
		//遍历页数
		for(int i=0; i<pages; i++) {
			rowIndex = 0;
			String title = titleBase + i;
			// 生成一个表格
			HSSFSheet sheet = workbook.createSheet(title);
			// 设置表格默认列宽度为15个字节
			sheet.setDefaultColumnWidth(defaultCellWidth+1);
			// 声明一个画图的顶级管理器
			HSSFPatriarch patriarch = sheet.createDrawingPatriarch();
			//标题行
			HSSFRow row = sheet.createRow(rowIndex);
			rowIndex++;
			//插入标题行
			for(int j=0; j<head.length+1; j++){
				HSSFCell cell = row.createCell(j);
				HSSFRichTextString text = null;
				if(j == 0){//标题行第一列不要编号
					text = new HSSFRichTextString("");
				}else{
					text = new HSSFRichTextString(head[j-1]);
				}
				cell.setCellStyle(style);
				cell.setCellValue(text);
			}

			HSSFFont font3 = workbook.createFont();
			font3.setColor(HSSFColor.BLUE.index);

			//开始遍历数据
			int start = i*pageSize;
			int end = (i+1)*pageSize;
			if(end >= listData.size()) {
				end = listData.size();
			}
			List<T> pageListData = new ArrayList<T>();
			pageListData = listData.subList(start, end);
			Iterator<T> it = pageListData.iterator();
			while(it.hasNext()) {
				row = sheet.createRow(rowIndex++);
				T t = it.next();
				for(int k=0; k<fields.length+1; k++) {



					HSSFCell cell = row.createCell(k);
					cell.setCellStyle(style);
					String textValue = null;
					if(k == 0){
						textValue = rowIndex-1+"";
					}else{
						Method m = null;
						String f = fields[k-1];
						if(selfFields.contains(f)) {
							m = t.getClass().getMethod("get"+StringUtil.firstToUp(f));
						}else if(parentFields.contains(f)){
							m = t.getClass().getSuperclass().getMethod("get"+StringUtil.firstToUp(f));
						}else {
							m= null;
						}
						textValue = m==null?"":et.dealValue(m.invoke(t));
					}
					Pattern p = Pattern.compile("^//d+(//.//d+)?{1}quot;");
					Matcher matcher = p.matcher(textValue);
					if (matcher.matches()) {
						// 是数字当作double处理
						cell.setCellValue(Double.parseDouble(textValue));
					} else {
						HSSFRichTextString richString = new HSSFRichTextString(
								textValue);
						//richString.applyFont(font3);
						cell.setCellValue(richString);
					}
				}
			}
		}

		if(!hasData) {
			HSSFSheet sheet = workbook.createSheet("空数据");
			HSSFRow row = sheet.createRow(0);
			sheet.addMergedRegion(new CellRangeAddress(0, 0,0,
					10));
			HSSFCell cell = row.createCell(0);
			cell.setCellStyle(style);
			HSSFRichTextString richString = new HSSFRichTextString("没有数据可以导出");

			HSSFFont font = workbook.createFont();
			font.setColor(HSSFColor.RED.index);

			richString.applyFont(font);
			cell.setCellValue(richString);

		}
		String agent = request.getHeader("User-Agent");
		fileName = FileUtils.encodeDownloadFilename(fileName,agent);
		response.setContentType("application/vnd.ms-excel");
		response.setCharacterEncoding("UTF-8");
		response.setHeader("Pragma", "public");
		response.setHeader("Cache-Control", "max-age=30");
		response.setHeader("Content-Disposition", "attachment; filename=" + fileName+".xls");
		workbook.write(response.getOutputStream());
	}

	private int getPages(List<T> listData) {
		int pages = listData.size() / this.pageSize;
		if(listData.size() % this.pageSize > 0) {
			pages += 1;
		}
		return pages;
	}
}
